package com.xmg.day05;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Author: mazhongqing
 * @Date: 2020/10/23 11:01
 */
public class CancelTaskDemo {
    static enum Result {
        SUCCESS, FAIL, CANCELLED
    }

    static List<MyTask> tasks = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        MyTask task1 = new MyTask("task1", 3, Result.SUCCESS);
        MyTask task2 = new MyTask("task2", 4, Result.SUCCESS);
        MyTask task3 = new MyTask("task3", 1, Result.FAIL);

        tasks.add(task1);
        tasks.add(task2);
        tasks.add(task3);

        for (MyTask task : tasks) {
            CompletableFuture future = CompletableFuture.supplyAsync(() -> task.runTask())
                    .thenAccept((result) -> callback(result, task));
        }

        System.in.read();
    }

    private static void callback(Result result, MyTask task) {
        //这里要考虑同步，除非cancel无状态，否则应该加同步
        if (result == Result.FAIL) {
            System.out.println("出问题了！！！");
            for (MyTask _task : tasks) {
                if (_task != task) {
                    _task.cancel();
                }
            }
        }
    }


    private static class MyTask {
        private String name;
        private Integer timeInSecond;
        private Result status;

        boolean cancelling = false;
        volatile boolean cancelled = false;

        public MyTask(String name, Integer timeInSecond, Result status) {
            this.name = name;
            this.timeInSecond = timeInSecond;
            this.status = status;
        }

        public Result runTask() {
            int interval = 100;
            int total = 0;
            try {
                for (; ; ) {
                    Thread.sleep(interval);
                    total += interval;
                    if (total >= timeInSecond) break;
                    if (cancelled) return Result.CANCELLED;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + "end!");
            return status;
        }

        public void cancel() {
            if (!cancelled) {
                synchronized (this) {
                    if (cancelled) return;
                    cancelling = true;
                    System.out.println(name + "cancelling");
                    try {
                        TimeUnit.MILLISECONDS.sleep(50);
                    } catch (Exception e) {

                    }
                    System.out.println(name + "cancelled");
                }
            }
            cancelled = true;
        }
    }
}
